package com.zx._06_JVM.chapter_02_gc;

import java.util.ArrayList;
import java.util.List;
//import sun.misc.Unsafe;

/**
 * @version v1.0
 * @Project: knowledge
 * @Title: OOMTest
 * @Description: 模拟OOM的测试代码，使用CMS垃圾回收器
 * @author: zhangxue
 * @date: 2019年9月22日下午2:54:32
 * @company: 未知之地
 * @Copyright: Copyright (c) 2019
 */
public class OOMTest {

    private int stackLength = 1;

    public static void main(String[] args) {
        OOMTest test = new OOMTest();
        //heap区OOM测试
        //-Xmx10M -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError
        test.heapOOM();

        //虚拟机栈和本地方法栈溢出
        // -Xmx10M -Xss128k -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError
        //test.stackOverflow();

        //metaspace OOM测试
        //-Xmx20M -XX:+UseConcMarkSweepGC -XX:MaxMetaspaceSize=10M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError
        //test.metaspaceOOM();

        //堆外内存 OOM测试
        //-Xmx20M -XX:+UseConcMarkSweepGC -XX:MaxDirectMemorySize=10M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError
        //test.directOOM();
    }

    /**
     * heap OOM测试
     */
    public void heapOOM() {
        List<OOMTest> list = new ArrayList<>();
        while (true) {
            list.add(new OOMTest());
        }
    }

    public void stackLeak() {
        stackLength += 1;
        stackLeak();
    }

    /**
     * VM Stack / Native method Stack 溢出测试
     */
    public void stackOverflow() {
        OOMTest test = new OOMTest();
        try {
            test.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + test.stackLength);
            throw e;
        }
    }

    public void genString() {
        List<String> list = new ArrayList<>();
        int i = 0;
        while (true) {
            list.add("string-" + i);
            i++;
        }
    }

    /**
     * metaspace/常量池 OOM测试
     */
    public void metaspaceOOM() {
        OOMTest test = new OOMTest();
        test.metaspaceOOM();
    }

    //public void allocDirectMemory() {
    //    final int _1MB = 1024 * 1024;
    //
    //    Field unsafeField = Unsafe.class.getDeclaredFields()[0];
    //    unsafeField.setAccessible(true);
    //    Unsafe unsafe = null;
    //    try {
    //        unsafe = (Unsafe) unsafeField.get(null);
    //    } catch (IllegalArgumentException | IllegalAccessException e) {
    //        e.printStackTrace();
    //    }
    //
    //    while (true) {
    //        unsafe.allocateMemory(_1MB);
    //    }
    //}

    /**
     * 堆外内存OOM测试
     */
    //public void directOOM() {
    //    OOMTest test = new OOMTest();
    //    test.allocDirectMemory();
    //}
}
